#define _CRT_SECURE_NO_WARNINGS 1
#include"snake.h"

#define POS_X 24
#define POS_Y 5

#define WALL L'□'
#define BODY L'●'
#define FOOD L'★'

//定位光标
void Setpos(short x,short y) {
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);

	COORD pos = { x,y };
	SetConsoleCursorPosition(houtput, pos);
}
//创建蛇
void CreateSnake(psnake ps) {
	int i;
	psnakenode cur = NULL;
	for (i = 0; i < 5; i++) {
		cur = (psnakenode)malloc(sizeof(snakenode));
		if (cur == NULL) {
			perror("CreatSnake::malloc");
			return;
		}
		cur->next = NULL;
		cur->x = POS_X + 2 * i;
		cur->y = POS_Y;
		if (ps ->_psnake==NULL) {
			ps->_psnake = cur;
		}
		else {
			cur->next = ps->_psnake;
			ps->_psnake = cur;
		}
		cur = ps->_psnake;
		while (cur) {
			Setpos(cur->x, cur->y);
			wprintf(L"%lc", BODY);
			cur=cur->next;
		}
	}
	ps->dir = RIGHT;
	ps->food_weight = 10;
	ps->score = 10;
	ps->sleep_time = 200;
	ps->gs = OK;
}

//创建食物
void CreateFood(psnake ps) {
	int x, y;
again:
	do {
		x = rand() % 53 + 2;
		y = rand() % 24 + 1;
	} while (x % 2 != 0);
	psnakenode cur = ps->_psnake;
	while (cur) {
		if (x == cur->x && y == cur->y)
			goto again;
		cur = cur->next;
	}
	psnakenode pFood = (psnakenode)malloc(sizeof(snakenode));
	if (pFood == NULL) {
		perror("CreateFood::malloc");
		return;
	}
	pFood->x = x;
	pFood->y = y;
	pFood->next = NULL;

	Setpos(x, y);
	wprintf(L"%lc", FOOD); 
	ps->_pfood = pFood;
}

void Welcometogame() {
	Setpos(45, 14);
	wprintf(L"欢迎来到贪吃蛇小游戏");
	Setpos(42, 20);
	system("pause");
	system("cls");
	Setpos(42, 14);
	wprintf(L"按↑ ↓ ← →键移动,F3加速,F4减速");
	Setpos(42, 15);
	wprintf(L"速度越快，食物的分值越高");
	Setpos(42, 20);
	system("pause");
	system("cls");
}

void Createmap() {
	//上
	for (int i = 0; i < 29; i++) {
		wprintf(L"%lc", WALL);
	}
	//下
	Setpos(0, 26);
	for (int i = 0; i < 29; i++) {
		wprintf(L"%lc", WALL);
	}
	//左
	for (int i = 1; i <= 25; i++) {
		Setpos(0, i);
		wprintf(L"%lc", WALL);
	}
	//右
	for (int i = 1; i <= 25; i++) {
		Setpos(56,i);
		wprintf(L"%lc", WALL);
	}
	//getchar();
}
//开始游戏
void GameStart(psnake ps) {
	system("mode con cols=100 lines=30");
	system("title 贪吃蛇");
	HANDLE houtput=GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO Cursorinfo;
	GetConsoleCursorInfo(houtput, &Cursorinfo);
	Cursorinfo.bVisible = false;
	SetConsoleCursorInfo(houtput, &Cursorinfo);
	//打印环境界面
	Welcometogame();
	//打印地图
	Createmap();
	//创建蛇
	CreateSnake(ps);
	//创建食物
	CreateFood(ps);
}

void PrintHelpInfo() {
	Setpos(60, 10);
	wprintf(L"不能穿墙，不能咬到自己");
	Setpos(60, 11);
	wprintf(L"按↑ ↓ ← →控制蛇的移动");
	Setpos(60, 12);
	wprintf(L"按F3加速,F4减速");
	Setpos(60, 13);
	wprintf(L"按Esc退出游戏，空格暂停游戏");
}

#define KEY_PRESS(vk) ((GetAsyncKeyState(vk)&1)?1:0)
//暂停
void Pause() {
	while (1) {
		Sleep(200);
		if (KEY_PRESS(VK_SPACE)) {
			break;
		}
	}
}
//判断下一步是否为食物
int NextIsFood(psnakenode pn, psnake ps) {
	return (pn->x == ps->_pfood->x && pn->y == ps->_pfood->y);
}
//吃食物
void EatFood(psnakenode pn, psnake ps) {
	ps->_pfood->next = ps->_psnake;
	ps->_psnake = ps->_pfood;
	free(pn);
	pn = NULL;

	psnakenode cur = ps->_psnake;
	while (cur) {
		Setpos(cur->x, cur->y);
		wprintf(L"%lc", BODY);
		cur = cur->next;
	}
	ps->score += ps->food_weight;
	//重新创建食物
	CreateFood(ps);
}
//没有食物
void NoFood(psnakenode pn, psnake ps) {
	pn->next = ps->_psnake;
	ps->_psnake = pn;

	psnakenode cur = ps->_psnake;
	while (cur->next->next!=NULL) {
		Setpos(cur->x, cur->y);
		wprintf(L"%lc", BODY);
		cur = cur->next;
	}

	Setpos(cur->next->x, cur->next->y);
	printf("  ");
	free(cur->next);
	cur->next = NULL;
}
//撞墙
void KillByWall(psnake ps) {
	if (ps->_psnake->x == 0 || ps->_psnake->x == 56 ||
		ps->_psnake->y == 0 || ps->_psnake->y == 26) {
		ps->gs = KILL_BY_WALL;
	}
}

void KillBySelf(psnake ps) {
	psnakenode cur = ps->_psnake->next;

	while (cur) {
		if (cur->x == ps->_psnake->x && cur->y == ps->_psnake->y) {
			ps->gs = KILL_BY_SELF;
			break;
		}
		cur = cur->next;
	}
}

//移动一步
void Snakemove(psnake ps) {
	psnakenode pn = (psnakenode)malloc(sizeof(snakenode));
	if (pn == NULL) {
		perror("Snakemove::malloc");
		return;
	}
	switch (ps->dir) {
	case UP:
		pn->x = ps->_psnake->x;
		pn->y = ps->_psnake->y - 1;
		break;
	case DOWN:
		pn->x = ps->_psnake->x;
		pn->y = ps->_psnake->y + 1;
		break;
	case LEFT:
		pn->x = ps->_psnake->x -2;
		pn->y = ps->_psnake->y;
		break;
	case RIGHT:
		pn->x = ps->_psnake->x+2;
		pn->y = ps->_psnake->y;
		break;
	}
	if (NextIsFood(pn, ps)) {
		EatFood(pn, ps);
	}
	else
		NoFood(pn, ps);
	KillByWall(ps);
	KillBySelf(ps);
}

void GameRun(psnake ps) {
	//打印帮助信息
	PrintHelpInfo();
	do {
		Setpos(60, 7);
		printf("得分:%d\n", ps->score);
		Setpos(60, 8);
		printf("食物分：%2d\n", ps->food_weight);

		if (KEY_PRESS(VK_UP) && ps->dir != DOWN) {
			ps->dir = UP;
		}
		else if (KEY_PRESS(VK_DOWN) && ps->dir != UP) {
			ps->dir = DOWN;
		}
		else if (KEY_PRESS(VK_LEFT) && ps->dir != RIGHT) {
			ps->dir = LEFT;
		}
		else if (KEY_PRESS(VK_RIGHT) && ps->dir != LEFT) {
			ps->dir = RIGHT;
		}
		else if (KEY_PRESS(VK_SPACE)) {
			//暂停
			Pause();
		}
		else if (KEY_PRESS(VK_ESCAPE)) {
			//退出
			ps->gs = END_NORMAL;
		}
		else if (KEY_PRESS(VK_F3)) {
			//加速
			if (ps->sleep_time > 80) {
				ps->sleep_time -= 30;
				ps->food_weight += 2;
			}
		}
		else if (KEY_PRESS(VK_F4)) {
			//减速
			ps->sleep_time += 30;
			ps->food_weight -= 2;
		}
		Snakemove(ps);
		Sleep(ps->sleep_time);
	} while (ps->gs == OK);
	
}

void GameEnd(psnake ps) {
	switch (ps->gs) {
	case END_NORMAL:
		printf("您主动退出游戏");
		break;
	case KILL_BY_WALL:
		printf("您撞墙了，游戏结束");
	case KILL_BY_SELF:
		printf("您撞到了自己");
	}
	psnakenode cur = ps->_psnake;
	while (cur) {
		psnakenode del = cur;
		cur = cur->next;
		free(del);
	}
}